package com.baymax.test.scene.demo

import android.animation.Animator
import android.animation.Keyframe
import android.animation.ObjectAnimator
import android.animation.PropertyValuesHolder
import android.graphics.*
import android.graphics.drawable.ColorDrawable
import android.graphics.drawable.GradientDrawable
import android.media.MediaPlayer
import android.os.Bundle
import android.util.Property
import android.view.*
import android.view.ViewGroup.*
import android.view.animation.DecelerateInterpolator
import android.view.animation.LinearInterpolator
import android.widget.Button
import android.widget.FrameLayout
import android.widget.LinearLayout
import android.widget.TextView
import androidx.core.animation.addListener
import androidx.core.view.setPadding
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import androidx.recyclerview.widget.RecyclerView.Adapter
import androidx.recyclerview.widget.RecyclerView.ItemDecoration
import com.baymax.test.scene.*
import com.baymax.test.scene.animation.RectEvaluator
import com.baymax.test.scene.drawable.DrawableUtils
import com.baymax.test.scene.drawable.InvlateDrawable
import kotlinx.coroutines.Job
import kotlin.math.abs

/**
 * @title:       标题
 * @project:     TestScene
 * @package:     com.baymax.test.scene
 * @class:       RvLayerScene
 * @description:
 * <p>
 * 类描述
 * </p>
 *
 * @version:   1.0
 * @createDate:   2023/4/19 15:34
 * @Copyright (C) 2023 YSTEN
 * @author:       xuyujian
 */
class RvLayerScene : BaseScene() {

    var select = false
    var layout = true
    var mediaPlayer: MediaPlayer? = null
    var job: Job = Job()
    var itemW = 280
    var itemH = 336
    val itemMargin = 20
    var index = 0
    lateinit var rvr: RecyclerView

    override fun onCreateView(p0: LayoutInflater, p1: ViewGroup, p2: Bundle?): View {

        return p1.newScrollContainer {
            clipChildren = false
            clipToPadding = false
            addView(LinearLayout(context).apply {
                addView(Button(context).apply {
                    val b = this
                    text = "switch mode"
                    isFocusable = true
                    background = DrawableUtils.createStateDrawable2(
                        ColorDrawable(Color.RED),
                        ColorDrawable(Color.GREEN)
                    )
                    setOnClickListener {
                        b.isSelected = !b.isSelected
                        select = b.isSelected
                    }
                })
                addView(Button(context).apply {
                    text = "changeW $itemW"
                    isFocusable = true
                    background = DrawableUtils.createGradientDrawable(
                        Color.GREEN,
                        floatArrayOf(20f, 20f, 20f, 20f, 20f, 20f, 0f, 0f)
                    )
                    setOnClickListener {
                        itemW += 3
                        text = "changeW $itemW"
                    }
                    setOnLongClickListener {
                        itemW -= 3
                        text = "changeW $itemW"
                        false
                    }
                    translationX = 20f

                })
                addView(Button(context).apply {
                    text = "changeH $itemH"
                    isFocusable = true
                    background = DrawableUtils.createStateDrawable2(
                        ColorDrawable(Color.RED),
                        ColorDrawable(Color.GREEN)
                    )
                    setOnClickListener {
                        itemH += 3
                        text = "changeH $itemH"
                    }
                    setOnLongClickListener {
                        itemH -= 3
                        text = "changeH $itemH"
                        false
                    }
                    translationX = 40f
                })


            }, MarginLayoutParams(-2, 60))

            setPadding(40)
            clipToPadding = false
            clipChildren = false

            val rv = RecyclerView(context).apply {

                background = DrawableUtils.createGradientDrawable(Color.BLUE, 2)
                layoutManager =
                    object : LinearLayoutManager(context, LinearLayoutManager.HORIZONTAL, false) {


                        override fun onLayoutChildren(
                            recycler: RecyclerView.Recycler?,
                            state: RecyclerView.State?
                        ) {
                            super.onLayoutChildren(recycler, state)
                        }

                        override fun onLayoutCompleted(state: RecyclerView.State?) {
                            super.onLayoutCompleted(state)
                        }

                        override fun generateDefaultLayoutParams(): RecyclerView.LayoutParams {
                            return RecyclerView.LayoutParams(itemW, itemH)
                        }

                        override fun requestChildRectangleOnScreen(
                            parent: RecyclerView,
                            child: View,
                            rect: Rect,
                            immediate: Boolean,
                            focusedChildVisible: Boolean
                        ): Boolean {
                            val vh = parent.findContainingViewHolder(child) as VH ?: return false
                            val s = vh.prop.currentScale
                            val x: Int =
                                getDecoratedLeft(child) - (parent.width - child.width + 20) / 2
                            if (x != 0) {
                                parent.scrollBy(x, 0);
                            }
                            return true
                        }
                    }
                addItemDecoration(object : ItemDecoration() {
                    override fun getItemOffsets(
                        outRect: Rect,
                        view: View,
                        parent: RecyclerView,
                        state: RecyclerView.State
                    ) {
                        println("getItemOffsets")
                        outRect.right = itemMargin
                    }
                })
                adapter = object : Adapter<VH>() {


                    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): VH =
                        VH(FrameLayout(context))

                    override fun onBindViewHolder(holder: VH, position: Int) {
                        holder.bindPos()
                        holder.itemView.alpha = 1f
                        println("onBindViewHolder $position")
                    }

                    override fun getItemCount() = 100


                }
                clipChildren = false
                clipToPadding = false
            }
            rvr = rv
            addView(rv, MarginLayoutParams(-1, if (select) -1 else itemH))


            val v = TextView(context).apply {
                isFocusable = true
                background = InvlateDrawable()
                setOnFocusChangeListener { v, fc ->
                    val f = if (fc) 1.2f else 1f
                    v.animate().scaleX(f).scaleY(f).start()
                }

            }
            val orgin = Paint()
            println("layerType $orgin")
            addView(v, MarginLayoutParams(100, 100).apply {
                leftMargin = 300
                topMargin = 30
            })
            addButton("change layer") {
                if (isSelected) {
                } else {
                }
                isSelected = !isSelected
            }
            val v1 = object : View(context) {
                val tp = Paint().apply {
                    setColor(Color.RED)
                    textSize = 24f
                }
                val p = Paint().apply {
                    setColor(Color.BLUE)
                }
                override fun onDraw(canvas: Canvas) {
                    super.onDraw(canvas)
                    canvas.drawText("hello" ,0f ,height / 2f, tp )
                    canvas.drawCircle(width / 2f, height / 2f, 40f, p)
                }
            }
            addView(v1, MarginLayoutParams(100, 100).apply {
                leftMargin = 300
                topMargin = 30

            })
            val ph = PropertyValuesHolder.ofFloat(ScaleProp(), 1f, 0f, -1f, 0f ,1f)
            ObjectAnimator.ofPropertyValuesHolder(v1, ph).apply {
                repeatCount = -1
                duration = 12000
                start()
            }
        }

    }


    inner class VH(val fl: FrameLayout) : RecyclerView.ViewHolder(fl) {
        val tv = TextView(fl.context)
        val player = Player(fl.context,)
        val surfaceView = FrameLayout(fl.context).apply {
            addView(player, MarginLayoutParams(-1, -1))
            setPadding(3)
            background = DrawableUtils.createGradientDrawable(Color.RED, 4)
        }

        init {
            fl.clipChildren = false
            fl.clipToPadding = false
            fl.isFocusable = true
            fl.setOnFocusChangeListener { v, hasFocus ->
                println("setOnFocusChangeListener hasFocus $hasFocus")
                println(v.layoutParams)
                scaleAnimation(v, hasFocus)
                fl.findViewById<TextView>(R.id.common_item_ext_subtitle).visibility =
                    if (hasFocus) View.VISIBLE else View.GONE

                if (hasFocus) {
                    v.animate().scaleX(1.2f).scaleY(1.2f)
                        .setStartDelay(300)
                        .setDuration(1000).start()
                    player.startLoop()
                } else {
                    v.animate().scaleX(1f).scaleY(1f)

                        .setStartDelay(300)
                        .setDuration(1000).start()
                    player.stop()
                }

            }
            tv.apply {
                gravity = Gravity.CENTER
                background = DrawableUtils.createStateDrawable(
                    DrawableUtils.createGradientDrawable(Color.GRAY, Color.GREEN, 4),
                    DrawableUtils.createGradientDrawable(Color.GRAY, Color.YELLOW, 4),
                )
//                setOnFocusChangeListener { v, hasFocus ->
//                    println("setOnFocusChangeListener hasFocus $hasFocus")
//                    println(v.layoutParams)
//                    scaleAnimation(v, hasFocus)
//                }
            }
            fl.addView(tv, FrameLayout.LayoutParams(-1, -1))
            fl.addView(View(fl.context).apply {
                setBackgroundColor(Color.GREEN)
            }, FrameLayout.LayoutParams(-1, 32, Gravity.BOTTOM))
            val v =
                layoutInflater.inflate(R.layout.panel_item_vs_title_subtitle_intruct_out, fl, false)
            fl.addView(v, FrameLayout.LayoutParams(-1, -2, Gravity.BOTTOM))

        }


        val prop = VHProp()
        private fun scaleAnimation(v: View, hasFocus: Boolean) {


            val ts = if (hasFocus) 1.07f else 1f
            prop.hasfocus = hasFocus
            val animator = ObjectAnimator.ofPropertyValuesHolder(
                this, PropertyValuesHolder.ofFloat(
                    prop, prop.currentScale, ts
                )
            )
            animator.addListener(onStart = { layout = false }, onEnd = { layout = true })
            animator.addListener(prop)
            animator.interpolator = DecelerateInterpolator()
            animator.duration = 800
            animator.start()
        }

        fun bindPos() {
            tv.text = this@VH.adapterPosition.toString()
//            fl.findViewById<TextView>(R.id.common_item_ext_title).text = "123456"
//            fl.findViewById<TextView>(R.id.common_item_ext_subtitle).text = "abcdhjkl"
        }

        inner class VHProp(
            var currentScale: Float = 1f,
            var hasfocus: Boolean = false,
        ) : Property<VH, Float>(Float::class.java, "scale"), Animator.AnimatorListener {

            override fun get(`object`: VH): Float = currentScale

            override fun set(`object`: VH, value: Float) {
                this.currentScale = value
                `object`.scale(value, hasfocus)
            }

            override fun onAnimationStart(animation: Animator) {
                println(itemView)
                if (surfaceView.parent != null) {
                    (itemView as ViewGroup).removeView(surfaceView)
                }
            }

            override fun onAnimationEnd(animation: Animator) {
                if (itemView.hasFocus() && surfaceView.parent == null) {
                    (itemView as FrameLayout).addView(
                        surfaceView,
                        1,
                        FrameLayout.LayoutParams(-1, -1),
                    )
                    if (!select) {
                        surfaceView.scaleX = 1 - abs(currentScale - 1)
                        surfaceView.scaleY = 1 - abs(currentScale - 1)
                        (surfaceView.layoutParams as? MarginLayoutParams)?.apply {
                            val lp = this

                            val viewW = itemW
                            val viewH = itemH
                            val sw = viewW * currentScale
                            val sh = viewH * currentScale
                            val offsetDx = (viewW - sw) / 2
                            val offsetDy = (viewH - sh) / 2
                            lp.width = (sw + 0.5f).toInt()
                            lp.height = (sh + 0.5f).toInt()
                            lp.leftMargin = (offsetDx - 0.5f).toInt()
                            lp.topMargin = (offsetDy - 0.5f).toInt()
//保持相对缩小的值
                            view.scaleX = 1 - abs(1 - currentScale)
                            view.scaleY = 1 - abs(1 - currentScale)
//                            val st = (420 * prop.currentScale).toInt()
//                            val offsetDx = (st - 420) / 2
//                            val lp = this
//                            lp.height = st
//                            lp.width = st
//                            lp.leftMargin = -offsetDx
//                            lp.topMargin =  -offsetDx


                            println("lp w${lp.width} ,h${lp.height}")
                            surfaceView.layoutParams = lp
                        }

                    }

                }
            }

            override fun onAnimationCancel(animation: Animator) {
            }

            override fun onAnimationRepeat(animation: Animator) {
            }


        }

        private fun scale(value: Float, hasfocus: Boolean) {
            if (select) {
                val lp = (this.itemView.layoutParams as RecyclerView.LayoutParams)
                println("w ${lp.width} h ${lp.height}")
                val st = (420 * value).toInt()
                val offsetDx = (st - 420) / 2
                lp.height = st
                lp.topMargin = -offsetDx

                lp.width = st
                lp.rightMargin = -offsetDx
                lp.leftMargin = -offsetDx
                this.itemView.layoutParams = lp

            } else {

                itemView.scaleX = value
                itemView.scaleY = value
            }


        }

    }

    class ScrollBy : Property<RecyclerView, Int>(Int::class.java, "ScrollBy") {
        var scrollBy = 0
        override fun get(`object`: RecyclerView): Int = scrollBy

        override fun set(`object`: RecyclerView, value: Int) {
            println("ScrollBy $value")
            if (value == 0) {
                reset()
            }
            `object`.scrollBy(value - scrollBy, 0)
            scrollBy = value
        }

        fun reset() {
            scrollBy = 0
        }
    }

    inner class AlphaFirst : Property<RecyclerView, Float>(Float::class.java, "ScrollBy") {

        override fun get(`object`: RecyclerView): Float = `object`.getChildAt(0)?.alpha ?: 0f

        override fun set(`object`: RecyclerView, value: Float) {
            println("AlphaFirst $value")
            `object`.findViewHolderForAdapterPosition(index)?.itemView?.alpha = value
        }
    }


    class ScaleProp : Property<View, Float>(Float::class.java, "scaleProp") {
        var scale: Float = 1f
        override fun get(`object`: View): Float = scale

        override fun set(`object`: View, value: Float) {
            `object`.scaleX = value
            `object`.scaleY = value
        }
    }
}


